package com.innovation.ic.sc.base.service.sc.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.innovation.ic.sc.base.mapper.sc.DepartmentMapper;
import com.innovation.ic.sc.base.model.sc.Department;

import com.innovation.ic.sc.base.model.sc.User;
import com.innovation.ic.sc.base.model.sc.UserManagement;
import com.innovation.ic.sc.base.pojo.constant.handler.RedisStorage;
import com.innovation.ic.sc.base.pojo.enums.RedisKeyPrefixEnum;
import com.innovation.ic.sc.base.pojo.variable.DepartmentPojo;
import com.innovation.ic.sc.base.pojo.variable.ServiceResult;
import com.innovation.ic.sc.base.service.ServiceHelper;
import com.innovation.ic.sc.base.service.sc.DepartmentService;
import com.innovation.ic.sc.base.vo.DepartmentVo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * DepartmentService的具体实现类
 */
@Service
@Transactional
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements DepartmentService {
    private static final Logger log = LoggerFactory.getLogger(DepartmentServiceImpl.class);

    @Resource
    private ServiceHelper serviceHelper;

    /**
     * //查询所有部门(当前登录用户下)
     *
     * @return
     */
    @Override
    public ServiceResult<List<Department>> findUserIdAllDepartment(String userId) {
        ServiceResult<List<Department>> serviceResult = new ServiceResult();
        List<Department> departmentSon = this.redisSelectDepartment(userId);//从redis获取数据
        serviceResult.setMessage(ServiceResult.SELECT_SUCCESS);
        serviceResult.setSuccess(Boolean.TRUE);
        serviceResult.setResult(departmentSon);
        return serviceResult;
    }

    /**
     * redis中获取部门信息（当前用户id 获取所有关联数据）
     *
     * @return
     */
    private List<Department> redisSelectDepartment(String userId) {
        String key = RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "_" + userId;
        Object redisDepartment = serviceHelper.getRedisManager().get(key);//通过userid从redis中获取对应数据
        if (redisDepartment == null) {//如果redis中没有的话就先从mysql中查询出来再存到缓存中
            List<String> userList = this.selectUser(userId);//返回主账号id与子账号id集合
            if (userList == null || userList.size() == 0) {
                return null;
            }
            QueryWrapper<Department> departmentQueryWrapper = new QueryWrapper<>();
            departmentQueryWrapper.in("user_id", userList);
            List<Department> departments = baseMapper.selectList(departmentQueryWrapper);//部门数据
            if (departments.size() == 0) {//只要没数据 就说明 当前主子账号都不存在 那就都添加为空字符串
                for (String data : userList) {
                    String redisKey = RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "_" + data;
                    serviceHelper.getRedisManager().set(redisKey, RedisStorage.EMPTY_VALUE);
                }
                return null;
            }
            for (String data : userList) { //并把数据存入缓存中
                String redisKey = RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "_" + data;
                String apiResultJson = JSONObject.toJSONString(departments, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
                serviceHelper.getRedisManager().set(redisKey, apiResultJson);
            }
            return departments;

        }
        if (redisDepartment.equals(RedisStorage.EMPTY_VALUE)) {//为空字符串或根本不存在redis中数据
            return null;
        }
        List<Department> redisAll = JSONObject.parseArray((String) redisDepartment, Department.class);//反序列化数据
        return redisAll;
    }

    /**
     * 添加部门信息
     *
     * @return
     */
    @Override
    public ServiceResult<Boolean> addDepartment(DepartmentVo departmentVo) {
        ServiceResult<Boolean> serviceResult = new ServiceResult();
        List<String> userList = this.selectUser(departmentVo.getUserId());//返回主账号id与子账号id集合
        if (userList == null) {
            serviceResult.setMessage(ServiceResult.INSERT_FAIL);
            serviceResult.setSuccess(Boolean.FALSE);
            return serviceResult;
        }
        //通过id与部门名称开始查询
        QueryWrapper<Department> departmentQueryWrapper = new QueryWrapper<>();
        departmentQueryWrapper.eq("department_name", departmentVo.getDepartmentName());
        departmentQueryWrapper.in("user_id", userList);
        List<Department> departments = baseMapper.selectList(departmentQueryWrapper);
        if (departments == null || departments.size() == 0) {//为空可以添加
            Department department = new Department();
            department.setUserId(departmentVo.getUserId());
            department.setDepartmentName(departmentVo.getDepartmentName());
            department.setCreateTime(new Date());
            baseMapper.insert(department);
            //清空历史数据
            List<String> redisDepartmentList = this.deleteRedisUser(userList);//返回(主子账号id并拼上redis对应前缀)
            serviceHelper.getRedisManager().del(redisDepartmentList);
            serviceResult.setMessage(ServiceResult.INSERT_SUCCESS);
            serviceResult.setSuccess(Boolean.TRUE);
            return serviceResult;
        } else {//已存在请重新输入部门名称
            serviceResult.setMessage(ServiceResult.INSERT_FAIL);
            serviceResult.setSuccess(Boolean.FALSE);
            return serviceResult;
        }
    }

    /**
     * 添加部门时进行同步redis
     *
     * @param userId
     * @param department
     * @return
     */
    private void addRedisDepartment(String userId, Department department) {
        User user = serviceHelper.getUserMapper().selectById(department.getUserId()); //获取fatherid
        DepartmentPojo departmentPojo = new DepartmentPojo();
        departmentPojo.setId(department.getId());
        departmentPojo.setDepartmentName(department.getDepartmentName());
        departmentPojo.setUserId(department.getUserId());
        departmentPojo.setCreateTime(department.getCreateTime());
        departmentPojo.setFatherId(user.getFatherId());
        String key = RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "_" + userId;
        Object redisDepartment = serviceHelper.getRedisManager().get(key);//通过userid从redis中获取对应数据
        if (RedisStorage.EMPTY_VALUE.equals(redisDepartment)) {
            List<Object> departmentList = new ArrayList<>();
            departmentList.add(departmentPojo);
            String apiResultJson = JSONObject.toJSONString(departmentList, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
            serviceHelper.getRedisManager().set(key, apiResultJson);
        } else {
            List<DepartmentPojo> redisAll = JSONObject.parseArray((String) redisDepartment, DepartmentPojo.class);//反序列化数据
            redisAll.add(departmentPojo);//添加新数据进集合
            String apiResultJson = JSONObject.toJSONString(redisAll, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
            serviceHelper.getRedisManager().set(key, apiResultJson);
        }
    }

    /**
     * 删除当前部门信息
     *
     * @return
     */
    @Override
    public ServiceResult<Boolean> dellDepartment(Integer id) {
        ServiceResult<Boolean> serviceResult = new ServiceResult();
        List<String> userIdList = new ArrayList<>();//存储所有用户id 用于 删除部门管理中redis中缓存
        Department department = baseMapper.selectById(id);//通过部门id从mysql中获取数据
        User user = serviceHelper.getUserMapper().selectById(department.getUserId());//当前用户
        List<String> redisDepartmentList = this.deleteRedisUser(user);//返回(主子账号id并拼上redis对应前缀)
        serviceHelper.getRedisManager().del(redisDepartmentList);

        QueryWrapper<UserManagement> userManagementQueryWrapper = new QueryWrapper<>();
        userManagementQueryWrapper.eq("department_id", id);
        List<UserManagement> userManagementList = serviceHelper.getUserManagementMapper().selectList(userManagementQueryWrapper);//获取跟当前部门关联的所有数据
        for (UserManagement userManagement : userManagementList) {
            List<String> selectUserList = this.selectUser(userManagement.getUserId());
            for (String userId : selectUserList) {
                userIdList.add(userId);
            }
        }
        userIdList = userIdList.stream().distinct().collect(Collectors.toList());//去重 用户id 避免重复删除redis
        List<String> redisKey = this.packageDeleteRedisKey(userIdList, id);//封装rediskey 用于部门管理批量删除
        serviceHelper.getRedisManager().del(redisKey);
        baseMapper.deleteById(id);//先删除部门表中数据
        serviceHelper.getUserManagementMapper().delete(userManagementQueryWrapper);//再删除部门对应中的人员

        serviceResult.setMessage(ServiceResult.DELETE_SUCCESS);
        serviceResult.setSuccess(Boolean.TRUE);
        return serviceResult;
    }

    private List<String> deleteRedisUser(User user) {//获取当前主账号id与所有的子账号id当做key去redis中删除相关数据
        List<String> list = new ArrayList<>();//用于存放主账号与子账号id
        if (user.getFatherId() == null) {//判断当前用户是主
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("father_id", user.getId());//需要查询主账号下的所有子账号id
            List<User> users = serviceHelper.getUserMapper().selectList(userQueryWrapper);//所有子账号id
            for (User user1 : users) {
                String id = RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "_" + user1.getId();//子账号拼redis对应前缀
                list.add(id);//子账号id存入
            }
            list.add(RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "_" + user.getId());//主账号拼redis对应前缀
        } else {//判断当前用户是子
            User userMain = serviceHelper.getUserMapper().selectById(user.getFatherId());//获取主账号
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("father_id", userMain.getId());//获取主账号下的所有子账号
            List<User> users = serviceHelper.getUserMapper().selectList(userQueryWrapper);//所有子账号id
            for (User user1 : users) {
                String id = RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "_" + user1.getId();//子账号拼redis对应前缀
                list.add(id);//子账号id存入
            }
            list.add(RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "_" + userMain.getId());//主账号拼redis对应前缀
        }
        return list;
    }

    private List<String> deleteRedisUser(List<String> userList) {//获取当前主账号id与所有的子账号id当做key去redis中删除相关数据
        List<String> list = new ArrayList<>();//用于存放主账号与子账号id
        for (String userId : userList) {
            String id = RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "_" + userId;//子账号拼redis对应前缀
            list.add(id);
        }
        return list;
    }

    private List<String> selectUser(String userId) {//获取当前主账号id与所有的子账号id
        List<String> list = new ArrayList<>();
        //添加前先查询一下
        User user = serviceHelper.getUserMapper().selectById(userId);//获取当前用户信息
        if (user == null) {
            return null;
        }
        if (user.getFatherId() == null) {//判断当前用户是主
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("father_id", user.getId());//需要查询主账号下的所有子账号id
            List<User> users = serviceHelper.getUserMapper().selectList(userQueryWrapper);//所有子账号id
            for (User user1 : users) {
                String id = user1.getId();
                list.add(id);//子账号id存入
            }
            list.add(user.getId());//主账号id存入
        } else {//判断当前用户是子
            User userMain = serviceHelper.getUserMapper().selectById(user.getFatherId());//获取主账号
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("father_id", userMain.getId());//获取主账号下的所有子账号
            List<User> users = serviceHelper.getUserMapper().selectList(userQueryWrapper);//所有子账号id
            for (User user1 : users) {
                String id = user1.getId();
                list.add(id);//子账号id存入
            }
            list.add(userMain.getId());//主账号id存入
        }
        return list;
    }

    /**
     * 初始化部门数据存入redis中
     */
    @Override
    public void initDepartmentData() {
        // 删除redis中的部门相关数据
        Boolean deleteResult = serviceHelper.getRedisManager().delRedisDataByKeyPrefix(RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "*");
        if (deleteResult) {
            log.info("删除[{}]开头的数据成功", RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode());
        }
        List<Department> departmentList = serviceHelper.getDepartmentMapper().selectList(null); // 获取部门表所有数据
        List<User> userList = serviceHelper.getUserMapper().selectList(null);//获取到用户表所有数据
        Map<String, List<Object>> departmentMap = new HashMap<>();//去除重复userid
        Map<String, User> userMap = new HashMap<>();//存放所有用户信息
        Map<String, List<Department>> map = new HashMap<>();//存放当前id下最终结果集部门数据
        for (User user : userList) {//用于绑定主账号信息
            userMap.put(user.getId(), user);
        }
        for (Department department : departmentList) {//去除重复数据
            if (departmentMap.containsKey(department.getUserId())) { //判断是否有相同用户id
                List<Object> list = departmentMap.get(department.getUserId());//获取map中数据
                list.add(department);//添加新的数据进入list集合
                departmentMap.put(department.getUserId(), list);//重新添加
            } else {
                ArrayList<Object> list = new ArrayList<>();
                list.add(department);
                departmentMap.put(department.getUserId(), list);
            }
        }

        for (Map.Entry entry : departmentMap.entrySet()) {//获取关联用户并获取关联部门数据
            User user = userMap.get(entry.getKey());
            List<String> usersList = this.selectUser(user.getId());//获取主账号与子账号所有id
            if (map.containsKey(entry.getKey())) {//如果有重复的就不会再执行避免浪费资源
                continue;
            }
            QueryWrapper<Department> departmentQueryWrapper = new QueryWrapper<>();
            departmentQueryWrapper.in("user_id", usersList);
            List<Department> departments = baseMapper.selectList(departmentQueryWrapper);
            for (String userid : usersList) {
                map.put(userid, departments);
            }

        }
        for (User userData : userList) {
            if (map.containsKey(userData.getId())) {//判断map中是否有重复的key
                String redisKey = RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "_" + userData.getId();
                String apiResultJson = JSONObject.toJSONString(map.get(userData.getId()), SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
                serviceHelper.getRedisManager().set(redisKey, apiResultJson);
            } else {
                String redisKey = RedisKeyPrefixEnum.DEPARTMENT_DATA.getCode() + "_" + userData.getId();
                serviceHelper.getRedisManager().set(redisKey, RedisStorage.EMPTY_VALUE);
            }
        }
    }

    /**
     * 封装部门
     */
    private DepartmentPojo packageDepartment(Department department, Map<String, User> userMap) {
        DepartmentPojo departmentPojo = new DepartmentPojo();
        departmentPojo.setId(department.getId());
        departmentPojo.setDepartmentName(department.getDepartmentName());
        departmentPojo.setUserId(department.getUserId());
        departmentPojo.setCreateTime(department.getCreateTime());
        //获取用户信息
        User user = userMap.get(department.getUserId());
        departmentPojo.setFatherId(user.getFatherId());
        return departmentPojo;
    }

    /**
     * 封装删除部门管理redis缓存key
     *
     * @param userIdList 所有用户id集合
     * @param id         部门id
     */
    private List<String> packageDeleteRedisKey(List<String> userIdList, Integer id) {
        ArrayList<String> list = new ArrayList<>();
        for (String userId : userIdList) {
            String redisKey = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + userId + "_" + id;
            list.add(redisKey);
        }
        return list;
    }
}
